﻿using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
using System.Text.RegularExpressions;

#if UNITY_EDITOR
using UnityEditor;
#endif

namespace Super
{
	public static class LangUtil
	{
		/// <summary>
		/// 获取所有的多语言keys
		/// 自定义keys和excel表格中的keys
		/// </summary>
		/// <returns></returns>
		public static HashSet<string> GetKeys()
		{
			HashSet<string> result = GetKeysByAddr(PathSettingSO.Ins.excelLangKeyPath);
			HashSet<string> customLangs = GetKeysByAddr(PathSettingSO.Ins.customLangKeyPath);
			result.UnionWith(customLangs);
			return result;
		}

		/// <summary>
		/// 获取多语言keys通过指定的addr（addressable资源文件的索引名称）
		/// </summary>
		/// <param name="addr"></param>
		/// <returns></returns>
		public static HashSet<string> GetKeysByAddr(string addr)
		{
			HashSet<string> result = new HashSet<string>();
			TextAsset textAsset = AssetUtil.LoadAsset<TextAsset>(addr);
			if (textAsset == null) return result;
			
			string[] lines = Regex.Split(textAsset.text, @"\r?\n");
			string line;
			for (int i = 0; i < lines.Length; i++)
			{
				line = lines[i].Trim();
				if (line.StartsWith("#") || string.IsNullOrEmpty(line))
				{
					continue;
				}

				result.Add(line);
			}
			return result;
		}



		/// <summary>
		/// 获取AA文件中的数据信息，文件中的keys，以及键值对的翻译信息
		/// </summary>
		/// <param name="addr"></param>
		/// <returns></returns>
		public static LangDataInfo GetDataInfoByAddr(string addr)
		{
			TextAsset textAsset = AssetUtil.LoadAsset<TextAsset>(addr);
			string[] lines = Regex.Split(textAsset.text, @"\r?\n");
			return GetDataInfoByLines(lines);
		}

		/// <summary>
		/// 获取文件中的数据信息，文件中的keys，以及键值对的翻译信息
		/// </summary>
		/// <param name="path"></param>
		/// <returns></returns>
		public static LangDataInfo GetDataInfoByPath(string path)
		{
			path = GlobalUtil.GetAbsolutePath(path);
			StreamReader SR = new StreamReader(path);
			string content = SR.ReadToEnd().Trim();
			string[] lines = Regex.Split(content, @"\r?\n");
			SR.Close();
			return GetDataInfoByLines(lines);
		}

		/// <summary>
		/// 获取'行数组'中的数据信息，文件中的keys，以及键值对的翻译信息
		/// </summary>
		/// <param name="lines"></param>
		/// <returns></returns>
		private static LangDataInfo GetDataInfoByLines(string[] lines)
		{
			LangDataInfo info = new LangDataInfo();
			string line;
			string key, value;
			for (int i = 0; i < lines.Length; i++)
			{
				line = lines[i].Trim();
				if (line.StartsWith("#") || string.IsNullOrEmpty(line))
				{
					continue;
				}
				List<int> equalSignIndexs = GlobalUtil.GetCharIndexList(line, '=');
				if (equalSignIndexs.Count > 0)
				{
					int midIndex = equalSignIndexs.Count/2;
					key = line.Substring(0, equalSignIndexs[midIndex]).Trim();
					value = line.Substring(equalSignIndexs[midIndex] + 1).Trim();
					info.keyValuePairs[key] = value;
				}
				else
				{
					key = line.Trim();
				}
				
				info.keys.Add(key);
			}
			return info;
		}



		/// <summary>
		/// 添加多语言key|追加写入
		/// </summary>
		/// <param name="key"></param>
		/// <param name="path">多语言文件的路径</param>
		public static void AddKey(string key, string path)
		{
			HashSet<string> keys = new HashSet<string> { key };
			AddKeys(keys, path);
		}

		/// <summary>
		/// 添加多语言keys|追加写入
		/// </summary>
		/// <param name="keys"></param>
		/// <param name="path">多语言文件的路径</param>
		/// <param name="templateAddr">多语言文件创建时的模板AA</param>
		public static void AddKeys(HashSet<string> keys, string path)
		{
#if UNITY_EDITOR
			path = GlobalUtil.GetAbsolutePath(path);
			bool isCreated = AssetUtil.TryCreateDirectoryAndFile(path);
			if (isCreated)
			{
				AssetUtil.CreateOrMoveEntry(ValueSettingSO.Ins.textAGroup, path);
			}

			string fileContent = File.ReadAllText(path);
			StreamWriter SW = new StreamWriter(path, true);
			
			if (!fileContent.EndsWith("\n"))
			{
				// 如果没有换行符，则写入一个换行符
				SW.WriteLine();
			}

			foreach (var key in keys)
			{
				SW.WriteLine(key);
			}
			SW.Close();
			AssetDatabase.Refresh();
#endif
		}

		/// <summary>
		/// 保存Keys|覆盖写入
		/// </summary>
		/// <param name="langKeys"></param>
		/// <param name="addr"></param>
		private static void SaveLangKeys(HashSet<string> langKeys, string addr, string tipText)
		{
			string path = GlobalUtil.GetAbsolutePath(addr);
			bool isCreated = AssetUtil.TryCreateDirectoryAndFile(path, tipText);
			if (isCreated)
			{
				AssetUtil.CreateOrMoveEntry(ValueSettingSO.Ins.textAGroup, addr);
			}
			StreamWriter streamWriter = new StreamWriter(path);
			streamWriter.AutoFlush = true;
			foreach (var key in langKeys)
			{
				streamWriter.WriteLine(key);
			}
			streamWriter.Flush();
			streamWriter.Close();
		}


		/// <summary>
		/// 尝试生成自定义多语言文件,文件已存在则忽略
		/// </summary>
		/// <returns></returns>
		public static bool TryGenerateCustomFile()
		{
			string path = GlobalUtil.GetAbsolutePath(PathSettingSO.Ins.customLangKeyPath);
			string tipText = TextUtil.GetCustomLangKeysTipText();
			bool isCreated = AssetUtil.TryCreateDirectoryAndFile(path, tipText);
			if (isCreated)
			{
				AssetUtil.CreateOrMoveEntry(ValueSettingSO.Ins.textAGroup, PathSettingSO.Ins.customLangKeyPath);
#if UNITY_EDITOR
				AssetDatabase.Refresh();
#endif
			}
			else
			{
				Debug.Log($"{path}文件已存在");
			}
			return isCreated;
		}

		/// <summary>
		/// 生成Keys文件，包含自定义和excel相关的keys集合
		/// </summary>
		public static void GenerateKeysFile()
		{
#if UNITY_EDITOR
			HashSet<string> langKeys = GetKeys();
			string tipText = TextUtil.GetLangKeysTipText();
			SaveLangKeys(langKeys, PathSettingSO.Ins.langKeysPath, tipText);
			AssetDatabase.Refresh();
			string logInfo = $"生成新LangKeys文件\n" +
				$"<a href=\"{PathSettingSO.Ins.langKeysPath}\">文件链接</a>";
			Debug.Log(logInfo);
#endif
		}

		/// <summary>
		/// 生成Excel相关的多语言文件
		/// </summary>
		public static void GenerateAllExcelFile()
		{
#if UNITY_EDITOR
			HashSet<string> langSet = new HashSet<string>();
			foreach (var item in ExcelNoteSO.Ins.notes)
			{
				ExcelNoteNode node = ExcelNoteSO.Ins.FindTableInfo(item.excelPath);
				for (int i = 0; i < node.tableNames.Count; i++)
				{
					ExcelTableInfo info = ExcelUtil.GetTableInfo(node.excelPath, i);
					if (info.hasLang)
					{
						langSet.UnionWith(GetExcelKeys(info));
						Debug.Log($"{item.excelPath}_{item.tableNames[i]} 表格多语言处理");
					}
				}
			}
			string tipText = TextUtil.GetExcelLangKeysTipText();
			SaveLangKeys(langSet, PathSettingSO.Ins.excelLangKeyPath, tipText);
			AssetDatabase.Refresh();
			Debug.Log("生成ExcelLang文件");
#endif
		}

		/// <summary>
		/// 获取Excel配置中新的Keys集合，与之前所有Keys相比较
		/// </summary>
		/// <param name="info"></param>
		/// <param name="langSet"></param>
		public static HashSet<string> GetExcelNewKeys(ExcelTableInfo info)
		{
			HashSet<string> langSet = new HashSet<string>();
			HashSet<string> oldLangs = GetKeys();
			string[][] allRowData = info.data.Skip(info.ignoreRow).ToArray();
			foreach (var rowData in allRowData)
			{
				string[] data = rowData.Skip(info.ignoreCol).ToArray();
				foreach (var index in info.langFieldIndexs)
				{
					if (!oldLangs.Contains(data[index]))
					{
						langSet.Add(data[index]);
					}
				}
			}
			return langSet;
		}

		/// <summary>
		/// 获取Excel中的Keys集合
		/// </summary>
		/// <param name="info"></param>
		/// <returns></returns>
		public static HashSet<string> GetExcelKeys(ExcelTableInfo info)
		{
			HashSet<string> langSet = new HashSet<string>();
			string[][] allRowData = info.data.Skip(info.ignoreRow).ToArray();
			foreach (var rowData in allRowData)
			{
				string[] data = rowData.Skip(info.ignoreCol).ToArray();
				foreach (var index in info.langFieldIndexs)
				{
					langSet.Add(data[index]);
				}
			}
			return langSet;
		}



		/// <summary>
		/// 获取当前多语言文件的路径或者AddressableName
		/// </summary>
		/// <returns></returns>
		public static string GetCurLangPath()
		{
			string assetPath = "";
			if (LangManager.Ins.langIndex == 0)
			{
				assetPath = AssetUtil.GetAssetPathByAddr(PathSettingSO.Ins.customLangKeyPath);
			}
			else
			{
				LangFileInfo langFileInfo = LangManager.Ins.fileList[LangManager.Ins.langIndex];
				if (langFileInfo.isCustom)
				{
					assetPath = langFileInfo.absolutePath;
				}
				else
				{
					assetPath = langFileInfo.addr;
				}
			}

			return assetPath;
		}


		/// <summary>
		/// 加载多语言文件
		/// </summary>
		/// <returns></returns>
		public static List<LangFileInfo> LoadFileList()
		{
			List<LangFileInfo> fileList = new List<LangFileInfo>();
			LangFileInfo langFileInfo = new LangFileInfo();
			langFileInfo.name = ValueSettingSO.Ins.defaultLangName;
			fileList.Add(langFileInfo);   //第一个为默认语言
			LoadLocalLang(fileList);
			TryLoadCustomLang(fileList);
			return fileList;
		}

		/// <summary>
		/// 加载本地多语言文件
		/// </summary>
		/// <param name="langList"></param>
		private static void LoadLocalLang(List<LangFileInfo> langList)
		{		
			List<TextAsset> textAssets = AssetUtil.LoadAssets<TextAsset>(ValueSettingSO.Ins.langLabel);
			if (textAssets == null || textAssets.Count == 0) return;
			foreach (TextAsset textAsset in textAssets)
			{
				if (textAsset != null && textAsset.name.StartsWith("Lang"))
				{
					LangFileInfo langFileInfo = new LangFileInfo();
					langFileInfo.name = textAsset.name.Replace("Lang", "");
					langFileInfo.isCustom = false;
					string fileName = $"{textAsset.name}.txt";
					langFileInfo.addr = $"{PathSettingSO.Ins.LangsDirectory}/{fileName}";
					langList.Add(langFileInfo);
				}
			}
		}

		/// <summary>
		/// 尝试加载PC自定义多语言文件
		/// </summary>
		/// <param name="langList"></param>
		/// <returns></returns>
		private static bool TryLoadCustomLang(List<LangFileInfo> langList)
		{
#if UNITY_STANDALONE_WIN
			string softPath = Application.dataPath.Replace(Application.productName + "_Data", "");
			string directoryPath = GlobalUtil.Combine(softPath, "Lang");
			DirectoryInfo directoryInfo = new DirectoryInfo(directoryPath);
			if (!directoryInfo.Exists)
			{
				return false;
			}
			foreach (FileInfo fileInfo in directoryInfo.GetFiles())
			{
				string fileName = Path.GetFileNameWithoutExtension(fileInfo.Name);
				if (fileName.StartsWith("Lang") && fileName != "Keys")
				{
					LangFileInfo langFileInfo = new LangFileInfo();
					langFileInfo.name = fileName.Replace("Lang", "");
					langFileInfo.isCustom = true;
					langFileInfo.absolutePath = fileInfo.FullName;
					langList.Add(langFileInfo);
				}

			}
			return true;
#else
			return false;
#endif
		}

	}
}
